﻿using PmSoft.Core.Domain.Auth;

namespace PmSoft.Web.Abstractions.Authorization;

/// <summary>
/// JWT 服务接口，定义了生成、验证和刷新 JWT Token 的核心方法。
/// </summary>
public interface IJwtService
{
	/// <summary>
	/// 为指定用户生成新的 Access Token 和 Refresh Token。
	/// </summary>
	/// <param name="user">已认证的用户对象，包含用户 ID、类型和租户信息。不得为 null。</param>
	/// <returns>包含 Access Token 和 Refresh Token 的元组，表示生成的令牌对。</returns>
	Task<(string AccessToken, string RefreshToken)> GenerateTokenAsync(IAuthedUser user);

	/// <summary>
	/// 刷新 Access Token 和 Refresh Token，使用旧的 Access Token 和 Refresh Token 获取新的令牌对。
	/// </summary>
	/// <param name="oldAccessToken">过期的 Access Token，用于验证用户身份和提取用户信息。不得为空或空白。</param>
	/// <param name="refreshToken">当前的 Refresh Token，用于验证刷新请求的有效性。不得为空或空白。</param>
	/// <returns>新的 Access Token 和 Refresh Token 的元组，如果刷新失败则返回 null。</returns>
	Task<(string NewAccessToken, string NewRefreshToken)?> RefreshTokenAsync(string oldAccessToken, string refreshToken);

	/// <summary>
	/// 解析并验证 JWT Token，返回对应的用户信息
	/// </summary>
	/// <param name="token">要解析的 JWT Token 字符串</param>
	/// <param name="allowExpired">是否允许过期令牌（用于刷新场景，默认 false）</param>
	/// <returns>解析成功且有效的 Token 返回对应的用户信息，否则返回 null</returns>
	Task<IAuthedUser?> ParseTokenAsync(string token, bool allowExpired = false);

	/// <summary>
	/// 检查指定的 Token 是否在白名单中有效。
	/// </summary>
	/// <param name="token">要检查的 JWT Token。不得为空或空白。</param>
	/// <param name="userId">用户 ID，用于定位缓存中的 Token。</param>
	/// <param name="tenantType">租户类型，可为空，用于区分多租户环境下的 Token。</param>
	/// <returns>如果 Token 在白名单中且匹配，则返回 true；否则返回 false。</returns>
	Task<bool> IsTokenInWhitelistAsync(string token, int userId, string? tenantType);

	/// <summary>
	/// 使指定用户的所有 Token 失效，并移除缓存中的记录。
	/// </summary>
	/// <param name="authedUser">已认证的用户对象，包含用户 ID 和租户信息。不得为 null。</param>
	/// <returns>表示异步操作的任务。</returns>
	Task InvalidateUserTokensAsync(IAuthedUser authedUser);

	/// <summary>
	/// 将指定的 Token 添加到黑名单，使其失效。
	/// </summary>
	/// <param name="token">要失效的 JWT Token。不得为空或空白。</param>
	/// <returns>表示异步操作的任务。</returns>
	Task InvalidateTokenAsync(string token);
}